//
//  EOSService.m
//  Bees
//
//  Created by NowYouCanSee on 2019/1/8.
//  Copyright © 2019 xiaohan. All rights reserved.
//

#import "EOSService.h"
#import "Sha256.h"
#import "uECC.h"
#import "rmd160.h"
#import "libbase58.h"
#import "NSDate+ExFoundation.h"
#import "ExcuteActions.h"

@implementation WalletError

@end

@implementation EOSService
- (void)getAccountInfoComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    [PPNetworkHelper POST:URL_Eos_get_account_info parameters:@{@"account_name":VALIDATE_STRING(self.wallet.wallet_name)} responseCache:nil success:^(id responseObject) {
        if (!IsNilOrNull(responseObject)) {
            self.accountResult = [EOSAccountInfo modelWithJSON:responseObject];
            self.wallet.balance = self.accountResult.core_liquid_balance;
            self.permission = @"";
            [self.accountResult.permissions enumerateObjectsUsingBlock:^(EOSPermissionsInfo * _Nonnull permissions, NSUInteger idx, BOOL * _Nonnull stopAll) {
                if ([permissions.perm_name isEqualToString:@"active"]) {
                    [permissions.required_auth.keys enumerateObjectsUsingBlock:^(EOSKey * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                        if ([obj.key isEqualToString:self.wallet.wallet_public_key]) {
                            self.permission = @"active";;
                            *stop = YES;
                            *stopAll=YES;
                        }
                    }];
                }
                if ([permissions.perm_name isEqualToString:@"owner"]) {
                    [permissions.required_auth.keys enumerateObjectsUsingBlock:^(EOSKey * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                        if ([obj.key isEqualToString:self.wallet.wallet_public_key]) {
                            self.permission = @"owner";;
                            *stop = YES;
                        }
                    }];
                }
            }];
            self.wallet.permission = self.permission;
            !complete?:complete(YES,nil);
        }else{
            !complete?:complete(NO,XLocalized(@"账号数据获取失败"));
        }
    } failure:^(NSError *error) {
        !complete?:complete(NO,kNetworkError);
    }];
}
///计算总资产
- (void)totalAssets{
    NSString*refund_request_net_amount = [self.accountResult.refund_request.net_amount getDigital]?:@"0.00";
    NSString*refund_request_cpu_amount = [self.accountResult.refund_request.cpu_amount getDigital]?:@"0.00";
    NSString*core_liquid_balance = [self.accountResult.core_liquid_balance getDigital]?:@"0.00";
    NSString*staked = [self.accountResult.voter_info.staked getDigital]?:@"0.00";
///可用余额+正在赎回余额+为别人抵押
    NSDecimalNumber*totalAssets=
    SNAdd(SNAdd(SNAdd(refund_request_net_amount, refund_request_cpu_amount).stringValue, core_liquid_balance), handlerDecimalNumber(SNDiv(staked, @(10000)), NSRoundDown, 4))
    ;
    self.accountResult.totalAssets = totalAssets.stringValue;
    self.accountResult.unit = [self.accountResult.total_resources.net_weight getUnit];
}

- (void)getAccountCurrencyBalanceCode:(NSString*)code account:(NSString*)account symbol:(NSString*)symbol complete:(void(^)(BOOL success,NSString*errorMsg,TokenInfo*tokenInfo))complete{
//    {"code":"eosio.token", "account":"testnetyy111", "symbol":"eos"}
    if (!code.length || !account.length) {
        return;
    }
    [PPNetworkHelper POST:URL_Eos_get_currency_balance parameters:@{@"code":code,@"account":account} responseCache:nil success:^(id responseObject) {
        if (!IsNilOrNull(responseObject)) {
            TokenInfo*token = [TokenInfo new];
            token.contract = code;
            token.symbol = symbol;
            token.balance = IsNilOrNull([responseObject objectOrNilAtIndex:0])?@"0.0000":[responseObject objectOrNilAtIndex:0];
//            if (![code isEqualToString:kContractName_EOSIOTOKEN]) {
//                Wallet*wallet = self.wallet;
//                wallet.contracts = @[token];
//                token.logo = @"http://data.beesgame.io/static/token_icon/bees.png";
//                [[XHDataBaseManager shareInstance]updateWalletToDB:wallet];
//            }
            !complete?:complete(YES,nil,token);
        }else{
            !complete?:complete(YES,nil,nil);
        }
    } failure:^(NSError *error) {
        NSData*data=error.userInfo[@"com.alamofire.serialization.response.error.data"];
        NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
        //        NSNumber*code = jsonDict[@"error"][@"code"];
        NSArray*details = jsonDict[@"error"][@"details"];
        NSDictionary*dic = [details objectOrNilAtIndex:0];
        !complete?:complete(NO,dic[@"message"],nil);
    }];
}

//- (void)getAccountCurrencyCodeComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
//    [PPNetworkHelper POST:URL_Eos_get_code parameters:@{@"account_name":CURRENT_WALLET.wallet_name} responseCache:^(id responseCache) {
//        
//    } success:^(id responseObject) {
//
//    } failure:^(NSError *error) {
//        
//    }];
//}

- (void)getBlockInfoComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    [PPNetworkHelper POST:URL_Eos_get_info parameters:@{} success:^(id responseObject) {
        if (ValidDict(responseObject)) {
            BlockChainInfo*chainInfo = [BlockChainInfo modelWithJSON:responseObject];
            self.ref_block_num = [NSString stringWithFormat:@"%@",chainInfo.head_block_num];
            self.chain_id = [NSObject convertHexStrToData:chainInfo.chain_id];
            self.expiration = [[[NSDate dateFromString: chainInfo.head_block_time] dateByAddingTimeInterval: 30] formatterToISO8601];
            NSString *js = @"function readUint32( tid, data, offset ){var hexNum= data.substring(2*offset+6,2*offset+8)+data.substring(2*offset+4,2*offset+6)+data.substring(2*offset+2,2*offset+4)+data.substring(2*offset,2*offset+2);var ret = parseInt(hexNum,16).toString(10);return(ret)}";
            [self.context evaluateScript:js];
            JSValue *n = [self.context[@"readUint32"] callWithArguments:@[@8,VALIDATE_STRING(chainInfo.head_block_id) , @8]];
            self.ref_block_prefix = [n toString];
            !complete?:complete(YES,nil);
        }else{
            !complete?:complete(NO,XLocalized(@"获取区块信息失败！"));
        }
    } failure:^(NSError *error) {
        NSData*data=error.userInfo[@"com.alamofire.serialization.response.error.data"];
        NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
        //        NSNumber*code = jsonDict[@"error"][@"code"];
        NSArray*details = jsonDict[@"error"][@"details"];
        NSDictionary*dic = [details objectOrNilAtIndex:0];
        !complete?:complete(NO,dic[@"message"]);
    }];
}

- (void)abiJsonTobinParameters:(NSDictionary*)parame complete:(void(^)(BOOL success,NSString*errorMsg))complete{
    
    [PPNetworkHelper POST:URL_Eos_abi_json_to_bin parameters:parame success:^(id responseObject) {
        if (ValidDict(responseObject)) {
            self.binargs = responseObject[@"binargs"];
            !complete?:complete(YES,nil);
        }else{
            !complete?:complete(NO,XLocalized(@"提交转账信息失败！"));
        }
    } failure:^(NSError *error) {
        NSData*data=error.userInfo[@"com.alamofire.serialization.response.error.data"];
        NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
//        NSNumber*code = jsonDict[@"error"][@"code"];
        NSArray*details = jsonDict[@"error"][@"details"];
        NSDictionary*dic = [details objectOrNilAtIndex:0];
        !complete?:complete(NO,dic[@"message"]);
        [kCurrentVC.view makeToast:dic[@"message"]];
        DLog(@"jsonDict \n %@",jsonDict);
    }];
}
- (void)signTransactionComplete:(void(^)(NSString*signatureStr))complete{
    if (!self.chain_id || !self.privateKey.length) {
        DLog(@"签名失败");
        return;
    }
    const int8_t *private_key = [[EOS_Key_Encode getRandomBytesDataWithWif:self.privateKey] bytes];
    Sha256 *sha256;
    if (self.binargsArr.count) {
         sha256 = [[Sha256 alloc] initWithData:[EosByteWriter getBytesForSignatureExcuteMultipleActions:self.chain_id andParams: [[self signParameters]objectForKey:@"transaction"] andCapacity:255]];
    }else{
        sha256 = [[Sha256 alloc]initWithData:[EosByteWriter getBytesForSignature:self.chain_id andParams:[[self signParameters]objectForKey:@"transaction"] andCapacity:255]];
    }
    int8_t signature[uECC_BYTES*2];
    int recId = uECC_sign_forbc(private_key, sha256.mHashBytesData.bytes, signature);
    if (recId == -1 ) {
        printf("could not find recid. Was this data signed with this key?\n");
    }else{
        unsigned char bin[65+4] = { 0 };
        unsigned char *rmdhash = NULL;
        int binlen = 65+4;
        int headerBytes = recId + 27 + 4;
        bin[0] = (unsigned char)headerBytes;
        memcpy(bin + 1, signature, uECC_BYTES * 2);
        
        unsigned char temp[67] = { 0 };
        memcpy(temp, bin, 65);
        memcpy(temp + 65, "K1", 2);
        
        rmdhash = RMD(temp, 67);
        memcpy(bin + 1 +  uECC_BYTES * 2, rmdhash, 4);
        
        char sigbin[100] = { 0 };
        size_t sigbinlen = 100;
        b58enc(sigbin, &sigbinlen, bin, binlen);
        NSString *signatureStr = [NSString stringWithFormat:@"SIG_K1_%@", [NSString stringWithUTF8String:sigbin]];
        DLog(@"signatureStr %@",signatureStr)
        self.signatureStr = signatureStr;
       
        if (self.binargsArr.count) {
             self.packed_trx = [[EosByteWriter getBytesForSignatureExcuteMultipleActions:nil andParams: [[self signParameters] objectForKey:@"transaction"] andCapacity:512] hexString];
        }else{
             self.packed_trx = [[EosByteWriter getBytesForSignature:nil andParams: [[self signParameters] objectForKey:@"transaction"] andCapacity:512] hexString];
        }
        if (self.signatureStr) {
            !complete?:complete(self.signatureStr);
        }
    }
}
- (void)pushTransactionComplete:(void(^)(BOOL success,BOOL executed,NSString*errorMsg))complete{
    [self getAccountInfoComplete:^(BOOL success, NSString * _Nonnull errorMsg) {
        if (success) {
            [self.accountResult.permissions enumerateObjectsUsingBlock:^(EOSPermissionsInfo * _Nonnull permissions, NSUInteger idx, BOOL * _Nonnull stopAll) {
                if ([permissions.perm_name isEqualToString:@"active"]) {
                    [permissions.required_auth.keys enumerateObjectsUsingBlock:^(EOSKey * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                        if ([obj.key isEqualToString:self.wallet.wallet_public_key]) {
                            self.permission = @"active";;
                            *stop = YES;
                            *stopAll=YES;
                        }
                    }];
                }
                if ([permissions.perm_name isEqualToString:@"owner"]) {
                    [permissions.required_auth.keys enumerateObjectsUsingBlock:^(EOSKey * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                        if ([obj.key isEqualToString:self.wallet.wallet_public_key]) {
                            self.permission = @"owner";;
                            *stop = YES;
                        }
                    }];
                }
            }];
            if (self.permission.length) {
                [self signTransactionComplete:^(NSString *signatureStr) {
                    if (signatureStr) {
                        [PPNetworkHelper POST:URL_Eos_push_transaction parameters:[self pushParameters] success:^(id responseObject) {
                            if (ValidDict(responseObject)) {
                                NSDictionary*act = [responseObject[@"processed"][@"action_traces"] objectOrNilAtIndex:0][@"act"];
                                if (ValidDict(act)) {
                                    NSDictionary*data = act[@"data"];
                                    if (ValidDict(data)) {
                                        self.transaction_id = responseObject[@"transaction_id"];
                                        //                            [self getTransactionDetailInfoComplete:^(BOOL success, BOOL executed, NSString *errorMsg) {
                                        !complete?:complete(YES,YES,@"操作失败");
                                        //                            }];
                                    }else{
                                        !complete?:complete(NO,NO,@"操作失败");
                                    }
                                }else{
                                    !complete?:complete(NO,NO,@"操作失败");
                                }
                            }else{
                                !complete?:complete(NO,NO,@"操作失败");
                            }
                        } failure:^(NSError *error) {
                            NSData*data=error.userInfo[@"com.alamofire.serialization.response.error.data"];
                            NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
                            NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
                            NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
                            //        NSNumber*code = jsonDict[@"error"][@"code"];
                            //        if ([code isEqualToNumber:@3080001]) {
                            //            !complete?:complete(NO,XLocalized(@"账号内存不足,请前往RAM资源界面购买"));
                            //        }else if ([code isEqualToNumber:@3050003]){
                            //            !complete?:complete(NO,XLocalized(@"账号内存不足,请前往RAM资源界面购买"));
                            //        }
                            NSDictionary*errorDic = jsonDict[@"error"];
                            NSArray*details = errorDic[@"details"];
                            NSDictionary*dic = [details objectOrNilAtIndex:0];
                            self.error = [WalletError new];
                            self.error.walletCode = [jsonDict[@"code"] integerValue];
                            self.error.errorCode = [errorDic[@"code"] integerValue];
                            self.error.errorName = errorDic[@"name"];
                            self.error.errorMessage = dic[@"message"];
                            switch (self.error.errorCode) {
                                case 3080004:
                                    self.error.errorMessage = @"CPU不足，抵押一些CPU";
                                    break;
                                case 3080002:
                                    self.error.errorMessage = @"网络资源不足，抵押一些资源";
                                    break;
                                case 3080001:
                                    self.error.errorMessage = @"内存不足，买些内存";
                                    break;
                                case 3050003:
                                    self.error.errorMessage = @"账户不存在，或者资产金额不正确等";
                                    break;
                                case 3050002:
                                    self.error.errorMessage = @"检查Action参数";
                                    break;
                                default:
                                    break;
                            }
                        
                            
                            !complete?:complete(NO,NO,self.error.errorMessage);
                            DLog(@"jsonDict \n %@",jsonDict);
                          
                        }];
                    }else{
                        !complete?:complete(NO,NO,@"操作失败");
                    }
                }];
                
            }else{
                [XAlertTool alertTitle:@"提示" message:@"当前账号权限已经变更，操作失败" cancelAction:nil sureAction:^{
                    
                }];
                !complete?:complete(NO,NO,@"当前账号权限已经变更，操作失败");
            }
        }else{
            !complete?:complete(NO,NO,errorMsg);
        }
    }];
    
}
///转账
- (void)transferFrom:(NSString*)from To:(NSString*)to quantity:(NSString*)quantity memo:(NSString*)memo complete:(void(^)(BOOL success,NSString*errorMsg))complete{
    if (/*!self.wallet.wallet_system.length ||*/ !from.length  || !to.length || !quantity.length || !memo || !self.action.length) {
        return;
    }
    [self getBlockInfoComplete:^(BOOL success, NSString *errorMsg) {
        if (success) {
            NSDictionary*parame = @{@"code":VALIDATE_STRING(self.account),@"action":VALIDATE_STRING(self.action),@"args":@{@"from":VALIDATE_STRING(from),@"to":VALIDATE_STRING(to),@"quantity":VALIDATE_STRING(quantity),@"memo":VALIDATE_STRING(memo)}} ;
            [self abiJsonTobinParameters:parame complete:^(BOOL success, NSString *errorMsg) {
                if (success) {
                    [self pushTransactionComplete:^(BOOL success,BOOL executed, NSString *errorMsg) {
                        if (success) {
                            !complete?:complete(YES,XLocalized(@"转账成功！"));
                        }else{
                            !complete?:complete(NO,errorMsg);
                        }
                    }];
                }
            }];
        }
    }];
//    //            获取当前最新的区块编号
//    [PPNetworkHelper POST:URL_Eos_get_info parameters:@{} success:^(id responseObject) {
//        if (ValidDict(responseObject)) {
//            BlockChainInfo*chainInfo = [BlockChainInfo modelWithJSON:responseObject];
//            self.ref_block_num = [NSString stringWithFormat:@"%@",chainInfo.head_block_num];
//            self.chain_id = [NSObject convertHexStrToData:chainInfo.chain_id];
//            self.expiration = [[[NSDate dateFromString: chainInfo.head_block_time] dateByAddingTimeInterval: 30] formatterToISO8601];
//            NSString *js = @"function readUint32( tid, data, offset ){var hexNum= data.substring(2*offset+6,2*offset+8)+data.substring(2*offset+4,2*offset+6)+data.substring(2*offset+2,2*offset+4)+data.substring(2*offset,2*offset+2);var ret = parseInt(hexNum,16).toString(10);return(ret)}";
//            [self.context evaluateScript:js];
//            JSValue *n = [self.context[@"readUint32"] callWithArguments:@[@8,VALIDATE_STRING(chainInfo.head_block_id) , @8]];
//            self.ref_block_prefix = [n toString];
//            NSDictionary*parame = @{@"code":VALIDATE_STRING(CURRENT_WALLET.wallet_system),@"action":VALIDATE_STRING(self.action),@"args":@{@"from":VALIDATE_STRING(from),@"to":VALIDATE_STRING(to),@"quantity":VALIDATE_STRING(quantity),@"memo":VALIDATE_STRING(memo)}} ;
//            [PPNetworkHelper POST:URL_Eos_abi_json_to_bin parameters:parame success:^(id responseObject) {
//                if (ValidDict(responseObject)) {
//                    self.binargs = responseObject[@"binargs"];
//                    const int8_t *private_key = [[EOS_Key_Encode getRandomBytesDataWithWif:self.privateKey] bytes];
//                    Sha256 *sha256 = [[Sha256 alloc]initWithData:[EosByteWriter getBytesForSignature:self.chain_id andParams:[[self signParameters]objectForKey:@"transaction"] andCapacity:255]];
//                    int8_t signature[uECC_BYTES*2];
//                    int recId = uECC_sign_forbc(private_key, sha256.mHashBytesData.bytes, signature);
//                    if (recId == -1 ) {
//                        printf("could not find recid. Was this data signed with this key?\n");
//                    }else{
//                        unsigned char bin[65+4] = { 0 };
//                        unsigned char *rmdhash = NULL;
//                        int binlen = 65+4;
//                        int headerBytes = recId + 27 + 4;
//                        bin[0] = (unsigned char)headerBytes;
//                        memcpy(bin + 1, signature, uECC_BYTES * 2);
//
//                        unsigned char temp[67] = { 0 };
//                        memcpy(temp, bin, 65);
//                        memcpy(temp + 65, "K1", 2);
//
//                        rmdhash = RMD(temp, 67);
//                        memcpy(bin + 1 +  uECC_BYTES * 2, rmdhash, 4);
//
//                        char sigbin[100] = { 0 };
//                        size_t sigbinlen = 100;
//                        b58enc(sigbin, &sigbinlen, bin, binlen);
//                        NSString *signatureStr = [NSString stringWithFormat:@"SIG_K1_%@", [NSString stringWithUTF8String:sigbin]];
//                        DLog(@"signatureStr %@",signatureStr)
//                        self.signatureStr = signatureStr;
//                        self.packed_trx = [[EosByteWriter getBytesForSignature:nil andParams: [[self signParameters] objectForKey:@"transaction"] andCapacity:512] hexString];
//                        [PPNetworkHelper POST:URL_Eos_push_transaction parameters:[self pushParameters] success:^(id responseObject) {
//                            if (ValidDict(responseObject)) {
//                                NSDictionary*act = [responseObject[@"processed"][@"action_traces"] objectOrNilAtIndex:0][@"act"];
//                                if (ValidDict(act)) {
//                                    NSDictionary*data = act[@"data"];
//                                    DLog(@"data ==  %@",data);
//                                    if (ValidDict(data)) {
//                                        !complete?:complete(YES,XLocalized(@"转账成功！"));
//                                    }else{
//                                        !complete?:complete(NO,XLocalized(@"转账失败！"));
//                                    }
//                                }else{
//                                    !complete?:complete(NO,XLocalized(@"转账失败！"));
//                                }
//                            }else{
//                                !complete?:complete(NO,XLocalized(@"转账失败！"));
//                            }
//                        } failure:^(NSError *error) {
//
//                        }];
//                    }
//                }else{
//                    !complete?:complete(NO,XLocalized(@"提交转账信息失败！"));
//                }
//            } failure:^(NSError *error) {
//
//            }];
//        }else{
//            !complete?:complete(NO,XLocalized(@"获取区块信息失败！"));
//        }
//    } failure:^(NSError *error) {
//
//    }];
  
}

- (void)mortgageResourcesComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    ///transfer ： 0为租借，1为过户
    [self getBlockInfoComplete:^(BOOL success, NSString *errorMsg) {
        if (success) {
            NSDictionary*parame = @{@"code":VALIDATE_STRING(kContractName_EOSIO),@"action":VALIDATE_STRING(self.action),@"args":@{@"from":VALIDATE_STRING(self.actor),@"receiver":VALIDATE_STRING(self.toUser),@"stake_net_quantity":VALIDATE_STRING(self.stake_net_quantity),@"stake_cpu_quantity":VALIDATE_STRING(self.stake_cpu_quantity),@"transfer":self.isMortgage?@"0":@"1"}} ;
            [self abiJsonTobinParameters:parame complete:^(BOOL success, NSString *errorMsg) {
                if (success) {
                    [self pushTransactionComplete:^(BOOL success, BOOL executed,NSString *errorMsg) {
                        if (success) {
                            !complete?:complete(YES,XLocalized(@"抵押成功！"));
                        }else{
                            !complete?:complete(NO,errorMsg);
                        }
                    }];
                }
            }];
        }
    }];
}

- (void)redemptionResourcesComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    [self getBlockInfoComplete:^(BOOL success, NSString *errorMsg) {
        if (success) {
            NSDictionary*parame = @{@"code":VALIDATE_STRING(kContractName_EOSIO),@"action":VALIDATE_STRING(self.action),@"args":@{@"from":VALIDATE_STRING(self.actor),@"receiver":VALIDATE_STRING(self.toUser),@"unstake_net_quantity":VALIDATE_STRING(self.stake_net_quantity),@"unstake_cpu_quantity":VALIDATE_STRING(self.stake_cpu_quantity)}} ;
            [self abiJsonTobinParameters:parame complete:^(BOOL success, NSString *errorMsg) {
                if (success) {
                    [self pushTransactionComplete:^(BOOL success,BOOL executed, NSString *errorMsg) {
                        if (success) {
                            !complete?:complete(YES,XLocalized(@"赎回成功！"));
                        }else{
                            !complete?:complete(NO,errorMsg);
                        }
                    }];
                }
            }];
        }
    }];
}

- (void)buyRamComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    [self getBlockInfoComplete:^(BOOL success, NSString *errorMsg) {
        if (success) {
            NSDictionary*parame = @{@"code":VALIDATE_STRING(kContractName_EOSIO),@"action":VALIDATE_STRING(self.action),@"args":@{@"payer":VALIDATE_STRING(self.actor),@"receiver":VALIDATE_STRING(self.toUser),@"quant":VALIDATE_STRING(self.ram_quant)}} ;
            [self abiJsonTobinParameters:parame complete:^(BOOL success, NSString *errorMsg) {
                if (success) {
                    [self pushTransactionComplete:^(BOOL success,BOOL executed, NSString *errorMsg) {
                        if (success) {
                            !complete?:complete(YES,XLocalized(@"购买内存成功！"));
                        }else{
                            !complete?:complete(NO,errorMsg);
                        }
                    }];
                }
            }];
        }
    }];
}


- (void)sellRamComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    [self getBlockInfoComplete:^(BOOL success, NSString *errorMsg) {
        if (success) {
            NSDictionary*parame = @{@"code":VALIDATE_STRING(kContractName_EOSIO),@"action":VALIDATE_STRING(self.action),@"args":@{@"account":VALIDATE_STRING(self.actor),@"bytes":VALIDATE_NUMBER(self.sell_ram)}} ;
            [self abiJsonTobinParameters:parame complete:^(BOOL success, NSString *errorMsg) {
                if (success) {
                    [self pushTransactionComplete:^(BOOL success,BOOL executed, NSString *errorMsg) {
                        if (success) {
                            !complete?:complete(YES,XLocalized(@"出售内存成功！"));
                        }else{
                            !complete?:complete(NO,errorMsg);
                        }
                    }];
                }
            }];
        }
    }];
}

- (void)getRammarketComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    [PPNetworkHelper POST:URL_Eos_getTableRows parameters:@{@"json": @(TRUE),@"code": @"eosio",@"scope":@"eosio",@"table":@"rammarket"} success:^(id responseObject) {
        if (!IsNilOrNull(responseObject)) {
//          RAM价格 = (n * quote.balance) / (n + base.balance / 1024)
            NSArray * rows = responseObject[@"rows"];
            NSDictionary * dic = [rows objectOrNilAtIndex:0];
            NSDictionary*base = [dic objectForKey:@"base"];
            NSDictionary*quote = [dic objectForKey:@"quote"];
            if (ValidDict(base) && ValidDict(quote)) {
                NSString *basebalance = [base[@"balance"] getDigital];
                NSString *quotebalance = [quote[@"balance"] getDigital];
               self.ram_balance = handlerDecimalNumber(SNDiv(SNMul(@1, quotebalance), SNAdd(SNDiv(basebalance, @1024), @1)), NSRoundPlain, 6).stringValue;
                !complete?:complete(YES,@"");
            }else{
                !complete?:complete(YES,XLocalized(@"数据异常！"));
            }
           
        }else{
            !complete?:complete(YES,XLocalized(@"数据异常！"));
        }
    } failure:^(NSError *error) {
        NSData*data=error.userInfo[@"com.alamofire.serialization.response.error.data"];
        NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
        //        NSNumber*code = jsonDict[@"error"][@"code"];
        //        if ([code isEqualToNumber:@3080001]) {
        //            !complete?:complete(NO,XLocalized(@"账号内存不足,请前往RAM资源界面购买"));
        //        }else if ([code isEqualToNumber:@3050003]){
        //            !complete?:complete(NO,XLocalized(@"账号内存不足,请前往RAM资源界面购买"));
        //        }
        NSArray*details = jsonDict[@"error"][@"details"];
        NSDictionary*dic = [details objectOrNilAtIndex:0];
        !complete?:complete(NO,dic[@"message"]);
        DLog(@"jsonDict \n %@",jsonDict);
    }];
}
- (void)abiBinJsonToParameters:(NSDictionary*)parame complete:(void(^)(BOOL success,NSString*errorMsg,NSDictionary*json))complete{
    [PPNetworkHelper POST:URL_Eos_abi_bin_to_json parameters:parame success:^(id responseObject) {
        if (ValidDict(responseObject[@"args"])) {
            !complete?:complete(YES,@"",responseObject[@"args"]);
        }else{
            !complete?:complete(NO,@"",nil);
        }
    } failure:^(NSError *error) {
        NSData*data=error.userInfo[@"com.alamofire.serialization.response.error.data"];
        NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
        //        NSNumber*code = jsonDict[@"error"][@"code"];
        NSArray*details = jsonDict[@"error"][@"details"];
        NSDictionary*dic = [details objectOrNilAtIndex:0];
        !complete?:complete(NO,dic[@"message"],nil);
        [kCurrentVC.view makeToast:dic[@"message"]];
        DLog(@"jsonDict \n %@",jsonDict);
    }];
}

- (void)getTableRowsParme:(NSDictionary*)parame complete:(void(^)(BOOL success,NSString*errorMsg,id data))complete{
    [PPNetworkHelper POST:URL_Eos_getTableRows parameters:parame success:^(id responseObject) {
        if (ValidDict(responseObject)) {
            !complete?:complete(YES,@"",responseObject);
        }else{
            !complete?:complete(NO,@"",nil);
        }
    } failure:^(NSError *error) {
        NSData*data=error.userInfo[@"com.alamofire.serialization.response.error.data"];
        NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
        //        NSNumber*code = jsonDict[@"error"][@"code"];
        NSArray*details = jsonDict[@"error"][@"details"];
        NSDictionary*dic = [details objectOrNilAtIndex:0];
        !complete?:complete(NO,dic[@"message"],nil);
        [kCurrentVC.view makeToast:dic[@"message"]];
        DLog(@"jsonDict \n %@",jsonDict);
    }];
}

- (void)getMyTokenListComplete:(void(^)(BOOL success,NSString*errorMsg))complete{
    
    [NetworkManager GET:URL_token_valuation parameters:@{@"account":VALIDATE_STRING(self.wallet.wallet_name)} responseCache:^(id responseCache) {
        KDISPATCH_GLOBAL_QUEUE_DEFAULT(^{
            XHBaseModel *base = [XHBaseModel modelWithJSON:responseCache];
            if ([base.code isEqualToNumber:@200]) {
                [self.myTokenList removeAllObjects];
                NSArray *symbol_list = [NSArray modelArrayWithClass:TokenInfo.class json:base.data[@"symbol_list"]];
                NSMutableArray *contracts = [NSMutableArray arrayWithArray:self.wallet.contracts];
                [symbol_list enumerateObjectsUsingBlock:^(TokenInfo*token, NSUInteger idx, BOOL * _Nonnull stop) {
                    if ([self.wallet.deleteCodes containsObject:token.code]) {
                        [contracts enumerateObjectsUsingBlock:^(TokenInfo* obj, NSUInteger idx, BOOL * _Nonnull stop) {
                            if ([obj.code isEqualToString:token.code]) {
                                [contracts removeObject:obj];
                            }
                        }];
                    }else{
                        [self.myTokenList addObject:token];
                    }
                }];
                self.max_valuation = base.data[@"max_valuation"];
                self.wallet.myTokenListJson = [self.myTokenList modelToJSONString];
                self.wallet.contractsJson = [contracts modelToJSONString];
                NSMutableArray *codes = [NSMutableArray arrayWithArray:self.wallet.codes];
                [symbol_list enumerateObjectsUsingBlock:^(TokenInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    if (![codes containsObject:obj.code] && ![self.wallet.deleteCodes containsObject:obj.code]) {
                        [codes addObject:obj.code];
                    }else if ([self.wallet.deleteCodes containsObject:obj.code]){
                        [codes removeObject:obj.code];
                    }
                }];
                self.wallet.codesJson = [codes modelToJSONString];
                KDISPATCH_MAIN_THREAD(^{
                    !complete?:complete(YES,base.message);
                });
            }else{
                KDISPATCH_MAIN_THREAD(^{
                    !complete?:complete(YES,base.message);
                });
            }
        });
//
    } success:^(id responseObject) {
        KDISPATCH_GLOBAL_QUEUE_DEFAULT(^{
            XHBaseModel *base = [XHBaseModel modelWithJSON:responseObject];
            if ([base.code isEqualToNumber:@200]) {
                [self.myTokenList removeAllObjects];
                NSArray *symbol_list = [NSArray modelArrayWithClass:TokenInfo.class json:base.data[@"symbol_list"]];
                NSMutableArray *contracts = [NSMutableArray arrayWithArray:self.wallet.contracts];
                [symbol_list enumerateObjectsUsingBlock:^(TokenInfo*token, NSUInteger idx, BOOL * _Nonnull stop) {
                    if ([self.wallet.deleteCodes containsObject:token.code]) {
                        [contracts enumerateObjectsUsingBlock:^(TokenInfo* obj, NSUInteger idx, BOOL * _Nonnull stop) {
                            if ([obj.code isEqualToString:token.code]) {
                                [contracts removeObject:obj];
                            }
                        }];
                    }else{
                        [self.myTokenList addObject:token];
                    }
                }];
                self.max_valuation = base.data[@"max_valuation"];
                self.wallet.myTokenListJson = [self.myTokenList modelToJSONString];
                self.wallet.contractsJson = [contracts modelToJSONString];
                NSMutableArray *codes = [NSMutableArray arrayWithArray:self.wallet.codes];
                [symbol_list enumerateObjectsUsingBlock:^(TokenInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    if (![codes containsObject:obj.code] && ![self.wallet.deleteCodes containsObject:obj.code]) {
                        [codes addObject:obj.code];
                    }else if ([self.wallet.deleteCodes containsObject:obj.code]){
                        [codes removeObject:obj.code];
                    }
                }];
                self.wallet.codesJson = [codes modelToJSONString];
                KDISPATCH_MAIN_THREAD(^{
                    !complete?:complete(YES,base.message);
                });
            }else{
                KDISPATCH_MAIN_THREAD(^{
                    !complete?:complete(YES,base.message);
                });
            }
        });
    } failure:^(NSError *error) {
        !complete?:complete(NO,kNetworkError);
    }];
}

- (void)getTokenInfoByTokenId:(NSString *)tokenId complete:(void(^)(BOOL success,NSString*errorMsg))complete{
    [NetworkManager GET:[URL_token stringByAppendingPathComponent:tokenId] parameters:@{@"id":tokenId} responseCache:^(id responseCache) {
        XHBaseModel *base = [XHBaseModel modelWithJSON:responseCache];
        if ([base.code isEqualToNumber:@200]) {
            self.tokenProjectModel = [TokenProjectModel modelWithJSON:base.data];
            !complete?:complete(YES,base.message);
        }else{
            !complete?:complete(NO,base.message);
        }
    } success:^(id responseObject) {
        XHBaseModel *base = [XHBaseModel modelWithJSON:responseObject];
        if ([base.code isEqualToNumber:@200]) {
            self.tokenProjectModel = [TokenProjectModel modelWithJSON:base.data];
            !complete?:complete(YES,base.message);
        }else{
            !complete?:complete(NO,base.message);
        }
    } failure:^(NSError *error) {
        !complete?:complete(NO,kNetworkError);
    }];
}

- (void)getTransactionDetailInfoComplete:(void(^)(BOOL success,XHBaseModel * data,NSString*errorMsg))complete{
    [PPNetworkHelper GET:URL_EOSPark_Mian parameters:@{@"module":@"transaction",@"action":@"get_transaction_detail_info",@"apikey":kEosParkKey,@"trx_id":VALIDATE_STRING(self.transaction_id)} success:^(id responseObject) {
        XHBaseModel *base = [XHBaseModel modelWithJSON:responseObject];
        if ([base.errNo isEqualToNumber:@0]) {
            !complete?:complete(YES,base,base.errmsg);
        }else{
            !complete?:complete(NO,nil,base.errmsg);
        }
    } failure:^(NSError *error) {
        !complete?:complete(NO,nil,kNetworkError);
    }];
}

-(NSDictionary *)signParameters{
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    NSMutableDictionary *transacDic = [NSMutableDictionary dictionary];
    [transacDic setObject:VALIDATE_STRING(self.ref_block_prefix) forKey:@"ref_block_prefix"];
    [transacDic setObject:VALIDATE_STRING(self.ref_block_num) forKey:@"ref_block_num"];
    [transacDic setObject:VALIDATE_STRING(self.expiration) forKey:@"expiration"];
    
    [transacDic setObject:@[] forKey:@"context_free_data"];
    [transacDic setObject:@[] forKey:@"signatures"];
    [transacDic setObject:@[] forKey:@"context_free_actions"];
    [transacDic setObject:@0 forKey:@"delay_sec"];
    [transacDic setObject:@0 forKey:@"max_kcpu_usage"];
    [transacDic setObject:@0 forKey:@"max_net_usage_words"];
    
   
    
    NSMutableDictionary *authorizationDict = [NSMutableDictionary dictionary];
    [authorizationDict setObject:VALIDATE_STRING(self.actor) forKey:@"actor"];
    [authorizationDict setObject:IsStrEmpty(self.permission) ? @"active":self.permission forKey:@"permission"];
    
  
    if (self.binargsArr.count) {
        NSMutableArray*actionDicts = [NSMutableArray array];
        [self.binargsArr enumerateObjectsUsingBlock:^(NSString* binargs, NSUInteger idx, BOOL * _Nonnull stop) {
            NSMutableDictionary *actionDict = [NSMutableDictionary dictionary];
            [actionDict setObject:VALIDATE_STRING(self.account) forKey:@"account"];
            [actionDict setObject:VALIDATE_STRING(self.action) forKey:@"name"];
            [actionDict setObject:VALIDATE_STRING(binargs) forKey:@"data"];
            [actionDict setObject:@[authorizationDict] forKey:@"authorization"];
            [actionDicts addObject:actionDict];
        }];
        [transacDic setObject:actionDicts.copy forKey:@"actions"];
    }else{
        NSMutableDictionary *actionDict = [NSMutableDictionary dictionary];
        [actionDict setObject:VALIDATE_STRING(self.account) forKey:@"account"];
        [actionDict setObject:VALIDATE_STRING(self.action) forKey:@"name"];
        [actionDict setObject:VALIDATE_STRING(self.binargs) forKey:@"data"];
        [actionDict setObject:@[authorizationDict] forKey:@"authorization"];
        [transacDic setObject:@[actionDict] forKey:@"actions"];
    }
    
    [params setObject:transacDic forKey:@"transaction"];
    DLog(@"transacDic %@",transacDic);
    NSMutableArray *available_keysArr = [NSMutableArray array];
    for (NSString *publicKey in self.available_keys) {
        if ([publicKey hasPrefix:@"EOS"]) {
            [available_keysArr addObject: publicKey];
        }
    }
    [params setObject:VALIDATE_ARRAY(available_keysArr) forKey:@"available_keys"];
    return params;
}

-(NSDictionary *)pushParameters{
    NSMutableDictionary *transacDic = [NSMutableDictionary dictionary];
    [transacDic setObject:VALIDATE_STRING(self.packed_trx) forKey:@"packed_trx"];
    [transacDic setObject:VALIDATE_ARRAY(@[self.signatureStr]) forKey:@"signatures"];
    [transacDic setObject:@"none" forKey:@"compression"];
    [transacDic setObject:@"00" forKey:@"packed_context_free_data"];
    DLog(@"transacDic %@", transacDic);
    return transacDic;
}
///账号授权
- (void)excuteSignatureMessageForScatterWithActor:(Wallet *)wallet signatureMessage:(NSString *)messageStr complete:(void(^)(BOOL success,NSString*errorMsg))complete{

    [WalletTool checkPrivateInputPasswordWith:wallet complete:^(BOOL result, NSString * _Nonnull privateKey) {
        if (result) {
            const int8_t *private_key = [[EOS_Key_Encode getRandomBytesDataWithWif:privateKey] bytes];
            //    const int8_t *private_key = [[EOS_Key_Encode getRandomBytesDataWithWif:@"5JLHReCKAn88SdEDtDt8DzMweDdD7eiaoc6w72jWFuVR4piNh5y"] bytes];
            //     [NSObject out_Int8_t:private_key andLength:32];
            if (!private_key) {
                !complete?:complete(NO,nil);
                return;
            }
            Sha256 *sha256 = [[Sha256 alloc] initWithData:[messageStr dataUsingEncoding:NSUTF8StringEncoding]];
            int8_t signature[uECC_BYTES*2];
            int recId = uECC_sign_forbc(private_key, sha256.mHashBytesData.bytes, signature);
            if (recId == -1 ) {
                printf("could not find recid. Was this data signed with this key?\n");
                !complete?:complete(NO,nil);
                return;
            }else{
                unsigned char bin[65+4] = { 0 };
                unsigned char *rmdhash = NULL;
                int binlen = 65+4;
                int headerBytes = recId + 27 + 4;
                bin[0] = (unsigned char)headerBytes;
                memcpy(bin + 1, signature, uECC_BYTES * 2);
                
                unsigned char temp[67] = { 0 };
                memcpy(temp, bin, 65);
                memcpy(temp + 65, "K1", 2);
                
                rmdhash = RMD(temp, 67);
                memcpy(bin + 1 +  uECC_BYTES * 2, rmdhash, 4);
                
                char sigbin[100] = { 0 };
                size_t sigbinlen = 100;
                b58enc(sigbin, &sigbinlen, bin, binlen);
                
                NSString *signatureStr = [NSString stringWithFormat:@"SIG_K1_%@", [NSString stringWithUTF8String:sigbin]];
                !complete?:complete(YES,signatureStr);
                NSLog(@"signatureStr %@", signatureStr);
            }
        }else{
            !complete?:complete(NO,nil);
        }
    }];
}


- (JSContext *)context{
    if (!_context) {
        _context = [[JSContext alloc] init];
    }
    return _context;
}
- (Wallet*)wallet{
    if (!_wallet) {
        _wallet = CURRENT_WALLET;
    }
    return _wallet;
}
- (NSMutableArray<TokenInfo*>*)myTokenList{
    if (!_myTokenList) {
        _myTokenList = [NSMutableArray array];
    }
    return _myTokenList;
}
@end
